/**
 *  Copyright 13.5.2001 oliver.keusemann@googlemail.com
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package de.xelerity.helper;

import java.io.UnsupportedEncodingException;
import java.util.Stack;

public class HexFunktionen {

	private static class EBCDICConverter {

		public String EBCDIC_CHARSET = "Cp1047";

		@SuppressWarnings("unused")
		public byte[] convert2CharSet(String pJavaString) throws UnsupportedEncodingException {
			if (pJavaString == null) {
				return new byte[0];
			}

			return pJavaString.getBytes(EBCDIC_CHARSET);
		}

		public String convertFromCharSet2JavaString(byte[] pCharArray) throws UnsupportedEncodingException {

			if (pCharArray == null || pCharArray.length == 0) {
				return "";
			}
			return new String(pCharArray, EBCDIC_CHARSET);
		}
	}

	//
	// Konvertiert "pint" zu einem bytearray mit der Hex-Darstellung
	//
	// z.b. 1568 ---> 06, 20; denn 1568(dez) = 0x0620;

	@SuppressWarnings("unchecked")
	public static byte[] int2Hexarray(int pint) {
		@SuppressWarnings("rawtypes")
		Stack st = new Stack();
		int ne = pint;
		if (ne == 0) {
			byte[] f = new byte[1];
			f[0] = 0;
			return f;
		}

		while (ne != 0) {
			int rest = ne % 256;
			ne = ne / 256;
			st.push(new Integer(rest));
		}

		int sz = st.size();
		byte[] f = new byte[sz];

		for (int i = 0; i < sz; i++) {
			f[i] = (byte) ((Integer) st.pop()).intValue();
		}

		return f;
	}

	public static String byte2HexString(byte pB) {
		int z = 0;
		if ((int) pB < 0) {
			z = (int) pB + 256;
		} else {
			z = (int) pB;
		}
		return Integer.toHexString(z).length() == 2 ? Integer.toHexString(z).toUpperCase() : "0"
				+ Integer.toHexString(z).toUpperCase();
	}

	public static String int2HexString(int f, int minlength) {
		HexString d = new HexString(f, minlength);
		return d.getString();
	}

	public static String HexDump(String s) {
		if (s == null) {
			return "";
		}
		return HexDump(s.getBytes());
	}

	public static String HexDump(byte[] pByteArray) {
		try {

			final int SPALTENBREITE = 16; // Anzahl Byte pro Zeile

			if (pByteArray == null) {
				return "<null>";
			}
			if (pByteArray.length == 0) {
				return "<Empty Array>";
			}

			int len = pByteArray.length;
			int firstposPipe = -1;

			int zeilen = len / SPALTENBREITE;
			int letzteSpaltenzahl = len % SPALTENBREITE;
			if (letzteSpaltenzahl > 0) {
				zeilen++;
			}

			String vollzeile = "";

			vollzeile = StringFunktionen.minLenLeft("Adr:", 4) + " |  " + StringFunktionen.minLenLeft("Hex:", 48) + "|  "
					+ StringFunktionen.minLenLeft("ANSI:", 16) + "  |  " + StringFunktionen.minLenLeft("EBCDIC:", 16)
					+ System.getProperty("line.separator");
			vollzeile = vollzeile + StringFunktionen.expandChar('-', 96) + System.getProperty("line.separator");

			for (int y = 0; y < zeilen; y++) {
				int anzahlspalten = SPALTENBREITE;
				if (y == zeilen - 1) {
					anzahlspalten = letzteSpaltenzahl;
				}

				String lLeftHex = int2HexString(y * SPALTENBREITE, 4) + " | ";
				for (int x = 0; x < anzahlspalten; x++) {
					byte b = pByteArray[y * SPALTENBREITE + x];
					String s = byte2HexString(b);
					lLeftHex = lLeftHex + s + " ";
				}

				String lRightHex = "";
				for (int x = 0; x < anzahlspalten; x++) {
					byte b = pByteArray[y * SPALTENBREITE + x];
					String s = ""; // Byte.toString(pByteArray[0]);
					// int ci = (int) b;
					s = "" + (char) b;
					String tmp = StringFunktionen.removewhiteChars("" + (char) b);
					if (tmp.trim().length() == 0) {
						s = ".";
					}

					lRightHex = lRightHex + s;
				}

				String lRightEBCDIC = "";
				for (int x = 0; x < anzahlspalten; x++) {
					byte b = pByteArray[y * SPALTENBREITE + x];
					String s = "";
					byte[] X = new byte[1];
					X[0] = b;
					s = new EBCDICConverter().convertFromCharSet2JavaString(X);
					String tmp = StringFunktionen.removewhiteChars("" + (char) b);
					if (tmp.trim().length() == 0) {
						s = ".";
					}

					lRightEBCDIC = lRightEBCDIC + s;
				}

				if (firstposPipe < 0) {
					firstposPipe = new String(lLeftHex.trim()).length();
					vollzeile = vollzeile + lLeftHex.trim() + "  |  " + lRightHex + "  |  " + lRightEBCDIC
							+ System.getProperty("line.separator");
				} else {
					vollzeile = vollzeile + StringFunktionen.minLenLeft(lLeftHex.trim(), firstposPipe) + "  |  "
							+ StringFunktionen.minLenLeft(lRightHex, 16) + "  |  " + lRightEBCDIC + System.getProperty("line.separator");
				}

			}

			return vollzeile.trim();
		} catch (Throwable e) {
			return "***Fehler bei der Ausfuehrung:" + e.getMessage();
		}
	}

	public static String HexStream(byte[] pByteArray) {
		try {
			if (pByteArray == null) {
				return "<null>";
			}
			if (pByteArray.length == 0) {
				return "<Empty Array>";
			}
			String lRet = "";
			for (int i = 0; i < pByteArray.length; i++) {
				lRet += byte2HexString((byte) pByteArray[i]);
			}

			return lRet;
		} catch (Throwable e) {
			return "<Error:" + e.getMessage() + ">";
		}
	}

}